/*
 * Copyright (C) 2010 Seapeak.Xu
 *
 * fostmq may be copied only under the terms of the GNU General
 * Public License V3, which may be found in the fostmq source kit.
 *
 * Created on: 2010-8-18
 * Author: Seapeak.Xu
 */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>

#include "fost_taskpool.h"
#include "fost_mem.h"
#include "fost_logger.h"
#include "fost_typedef.h"
#include "fost_thread.h"
#include "fost_mgnb.h"

typedef struct taskpool_type
{
	pthread_mutex_t locker;
	task_t *list;
	bool is_free;
}taskpool_t;

static taskpool_t *taskpool;

static void elt_destroy(task_t *elt);
static void elt_clear(task_t *elt);

static void elt_destroy(task_t *elt)
{
	if (NULL != elt->resp_bodybuff)
	{
		FOST_FREE(elt->resp_bodybuff);
	}
	if(NULL != elt->req_bodybuff)
	{
		FOST_FREE(elt->req_bodybuff);
	}
	if (NULL != elt->event_base)
	{
		event_base_free(elt->event_base);
		elt->event_base = NULL;
	}
	FOST_FREE(elt);
}

static void elt_clear(task_t *elt)
{
	elt->sock = 0;
	elt->offset = 0;
	elt->session_type = unspecified;

	memset(elt->req_headerbuff, 0, HEADERLEN + 1);
	memset(elt->resp_headerbuff, 0, HEADERLEN + 1);
	memset(&(elt->req_header),0,sizeof(header_t));
	memset(&(elt->resp_header),0,sizeof(header_t));

	if (NULL != elt->req_bodybuff)
	{
		FOST_FREE(elt->req_bodybuff);
	}
	if(NULL != elt->resp_bodybuff)
	{
		FOST_FREE(elt->resp_bodybuff);
	}

	return;
}

int taskpool_init(const size_t numb, const size_t timeout,header_handler_proxy header_proxy,body_handler_proxy body_proxy)
{
	int result = 0;
	struct timeval network_timeout;
	network_timeout.tv_sec = timeout;
	network_timeout.tv_usec = 0;
	if (0 == numb)
	{
		log_error("File:%s,Line:%d,Function:%s.the task pool size is 0.",
				__FILE__, __LINE__, __FUNCTION__);
		return -1;
	}

	taskpool = (taskpool_t *) fost_calloc1(sizeof(taskpool_t));
	if(NULL == taskpool)
	{
		log_error("File:%s,Line:%d,Function:%s.mallco memory for taskpool is error.Errno:%d,Info:%s.",
				__FILE__,__LINE__,__FUNCTION__,errno,strerror(errno));
		return -1;
	}
	do
	{
		if(0 != thread_mutexlocker_init(&(taskpool->locker)))
		{
			log_error("File:%s,Line:%d,Function:%s.init the taskpool mutexlocker is error.",
					__FILE__,__LINE__,__FUNCTION__);
			result = -1;
			break;
		}

		do
		{
			taskpool->list = (task_t *) fost_calloc(numb,sizeof(task_t));
			if(NULL == taskpool->list)
			{
				log_error("File:%s,Line:%d,Function:%s.malloc memory fot taskpool list is error.Errno:%d,Info:%s",
						__FILE__,__LINE__,__FUNCTION__,errno,strerror(errno));
				result = -1;
				break;
			}
			do
			{
				int i;
				int end_postion = numb - 1;
				task_t *current_ptr = NULL;
				for (i = end_postion; i >= 0; i--)//Descending
				{
					(taskpool->list + i)->event_base = event_base_new();
					(taskpool->list + i)->timeout = network_timeout;
					(taskpool->list + i)->offset = 0;
					(taskpool->list + i)->session_type = unspecified;
					(taskpool->list + i)->index = i;
					(taskpool->list + i)->header_proxy = header_proxy;
					(taskpool->list + i)->body_proxy = body_proxy;

					if(0 != thread_mutexlocker_init(&((taskpool->list + i)->locker)))
					{
						log_error("File:%s,Line:%d,Function:%s.init the taskpool elt locker is error.",
								__FILE__,__LINE__,__FUNCTION__);
						result = -1;
						break;
					}
					memset((taskpool->list + i)->req_headerbuff,'\0',HEADERLEN + 1);
					memset((taskpool->list + i)->resp_headerbuff,'\0',HEADERLEN  + 1);

					(taskpool->list + i)->next = current_ptr;
					current_ptr = taskpool->list + i;
				}
				taskpool->is_free = false;
				return 0;			
			}while(false);
			FOST_FREE(taskpool->list);				
		}while(false);
		pthread_mutex_destroy(&(taskpool->locker));
	}while(false);
	FOST_FREE(taskpool);

	return result;

}

int taskpool_push(task_t *elt)
{
	if(0 != pthread_mutex_lock(&(taskpool->locker)))
	{
		log_error("File:%s,Line:%d,Function:%s.Get task pool locker is error when pop the element.Errno:%d,Info:%s.",
				__FILE__, __LINE__, __FUNCTION__, errno,strerror(errno));
		return -1;
	}

	do
	{
		elt_clear(elt);
	}while(false);
	pthread_mutex_unlock(&(taskpool->locker));
	return 0;
}

task_t *taskpool_pop(int idx)
{
	task_t *elt;

	if(0 != pthread_mutex_lock(&(taskpool->locker)))
	{
		log_error("File:%s,Line:%d,Function:%s.Get task pool locker is error when pop the element.Errno:%d,Info:%s.",
				__FILE__, __LINE__, __FUNCTION__, errno,strerror(errno));
		return NULL;
	}

	do
	{
		if(taskpool->is_free || !g_loop)
		{
			elt = NULL;
			log_warn("File:%s,Line:%d,Function:%s.the task pool is free or the process is over.",
					__FILE__, __LINE__, __FUNCTION__);
			break;
		}

		elt = taskpool->list + idx;
	}while(false);
	pthread_mutex_unlock(&(taskpool->locker));
	return elt;
}

int taskpool_destroy()
{
	/* 
	   task_t *elt;
	   if (0 != pthread_mutex_lock(&locker))
	   {
	   log_error(
	   "File:%s,Line:%d,Function:%s.Get task pool locker is error when destroy the task pool.Errno:%d,Info:%s.",
	   __FILE__, __LINE__, __FUNCTION__, errno,strerror(errno));
	   return -1;
	   }

	   do
	   {
	   is_free = true;
	   while(0 != busy_size)
	   {
	   sleep(30);
	   }


	   elt = taskpool;
	   thread_mutexlocker_destory(&(elt->locker));
	   while (NULL != elt)
	   {
	   elt_destroy(elt);
	   }
	   if (NULL != taskpool)
	   {
	   fost_free(&taskpool);
	//taskpool = NULL;
	}
	current_ptr = NULL;
	} while (false);
	pthread_mutex_unlock(&locker);
	*/
	return 0;
}
